package com.cheng.gmall.item.controller;

import com.cheng.gmall.common.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author Cheng-02
 * @version V1.0
 * @Package com.cheng.gmall.item.controller
 * @date 2024/5/31 下午7:37
 */

@Slf4j
@RestController
public class ReidissonController {
    public String x;
    @Autowired
    RedissonClient redissonClient;

    /*
     * 信号量
     * 能增能减
     * */
    @GetMapping("/init/park")
    public Result Semaphore() {

        RSemaphore semaphore = redissonClient.getSemaphore("xxxx");
        semaphore.trySetPermits(5);


        return Result.ok("停车场初始化完成");
    }

    @GetMapping("/car/park")
    public Result park() throws InterruptedException {
        RSemaphore semaphore = redissonClient.getSemaphore("xxxx");
        //要一个
        semaphore.acquire(1);
        return Result.ok("停车成功");
    }

    @GetMapping("/car/go")
    public Result cargo() throws InterruptedException {
        RSemaphore semaphore = redissonClient.getSemaphore("xxxx");
        //要一个
        semaphore.release(1);
        return Result.ok("停车走了");
    }







    /*
     * 闭锁
     *  只能减
     * */

    @GetMapping("shenlong")
    public Result shenlong() throws InterruptedException {
        RCountDownLatch qilongzhu = redissonClient.getCountDownLatch("qilongzhu");
        qilongzhu.trySetCount(7L);


        log.info("等待召唤");
        qilongzhu.await();


        return Result.ok("神龙....");
    }

    @GetMapping("/longzhu")
    public Result longzhu() {
        RCountDownLatch qilongzhu = redissonClient.getCountDownLatch("qilongzhu");
        qilongzhu.countDown();

        return Result.ok("一颗到手...");

    }


    /*
     * 读写锁：  改数据
     *
     * 读读无锁
     * 写写有锁
     *
     * 写读有锁  读要等待
     * 读写：有锁，写要等待
     *
     * */
    @GetMapping("/write")
    public Result write() {
        //1.获取读写锁
        RReadWriteLock rwLock = redissonClient.getReadWriteLock("hhhh-rw");
        //获取写锁
        RLock wLock = rwLock.writeLock();
        try {
            wLock.lock();
            log.info("业务正在进行数据修改");
            TimeUnit.SECONDS.sleep(15);
            x = UUID.randomUUID().toString();
            log.info("业务修改完成");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                wLock.unlock();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return Result.ok(x);
    }

    @GetMapping("/read")
    public Result read() {
        //1.获取读写锁
        RReadWriteLock rwLock = redissonClient.getReadWriteLock("hhhh-rw");
        //2.获取读锁
        RLock rLock = rwLock.readLock();
        try {
            //加读锁
            rLock.lock();
            log.info("业务正在远程获取数据中");
            TimeUnit.SECONDS.sleep(10);

        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            rLock.unlock();
        }

        return Result.ok(x);

    }


    @GetMapping("/redisson/lock")
    public Result lock() {
        //获取一把锁
        RLock lock = redissonClient.getLock("haha-lock");
        //加锁
        try {
//            lock.lock();//阻塞式加锁，一定要等到锁，  得到锁：锁的默认时间30s
//            //阻塞式加锁（传了锁释放时间，）。 一定要等到锁，  得到锁：锁的默认时间是40s，而且没有续期
//
//            lock.lock(10, TimeUnit.SECONDS);
            //非阻塞式加锁，尝试加锁，加锁成功返回true，加锁失败返回false
            boolean tryLock = lock.tryLock();
            //尝试加锁，加锁成功返回true（10s内返回true），加锁失败返回false，最多等待10s   10s以后返回false   默认时间30s
            lock.tryLock(10, TimeUnit.SECONDS);
            //尝试加锁，加锁成功返回true，加锁失败返回false，最多等待10s，上锁时间为10s
            lock.tryLock(10, 10, TimeUnit.SECONDS);
            log.info("业务真正执行");
            try {
                TimeUnit.SECONDS.sleep(60);
                log.info("业务执行完成...");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                //解锁
                lock.unlock();//同步解锁
                log.info("解锁完成");
            } catch (Exception e) {
            }
        }
        return Result.ok();
    }

    @GetMapping("/redisson/client")
    public Result client() {
        log.info("redissonclient:{ }" + redissonClient);
        return Result.ok(redissonClient);
    }
}
